﻿#include <ctype.h>
#include <locale.h>
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>

#include "hello_h.h"
#pragma comment(lib, "Rpcrt4.lib")

HANDLE g_hEvent = NULL;
wchar_t msg[128] = {0};
static HANDLE hThread = NULL;
DWORD WINAPI ThreadMakeMsg(LPVOID argv);

void server_EnableReceiveMsg()
{
    unsigned long ulCode = 0;
    wprintf(L"消息接收已打开\n");
    RpcTryExcept
    {
        // 调用客户端的回调函数
        while (true) {
            WaitForSingleObject(g_hEvent, INFINITE);   // 等待消息
            client_ReceiveMsgCb((const wchar_t *)msg); // 调用接收消息回调
            ResetEvent(g_hEvent);                      // 重置消息状态
        }
    }
    RpcExcept(1)
    {
        ulCode = RpcExceptionCode();
        printf("Runtime reported exception 0x%lx = %ld\n", ulCode, ulCode);
    }
    RpcEndExcept
}

DWORD WINAPI ThreadMakeMsg(LPVOID argv)
{
    DWORD count = 0;
    while (TRUE) {
        count = 100 + rand() % 2000;
        wsprintf(msg, L"Message from Server(%ld)", count); // 生成消息

        SetEvent(g_hEvent); // 发送消息通知
        Sleep(count);       // 模拟消息生成间隔
    }

    return 0;
}

void server_Shutdown(void)
{
    RPC_STATUS status = RPC_S_OK;

    CloseHandle(hThread);
    status = RpcMgmtStopServerListening(NULL);

    if (status) {
        exit(status);
    }

    status = RpcServerUnregisterIf(NULL, NULL, FALSE);

    if (status) {
        exit(status);
    }
}

// Naive security callback.
RPC_STATUS CALLBACK SecurityCallback(RPC_IF_HANDLE /*hInterface*/, void * /*pBindingHandle*/)
{
    return RPC_S_OK; // Always allow anyone.
}

int main()
{
    RPC_STATUS status;
    unsigned long ulCode = 0;
    setlocale(LC_ALL, "chs"); // 这是个大坑，不设置中文直接不见了。。。
    // Uses the protocol combined with the endpoint for receiving
    // remote procedure calls.
    status = RpcServerUseProtseqEp(reinterpret_cast<RPC_WSTR>((RPC_WSTR)L"ncalrpc"), // Use TCP/IP protocol
                                   RPC_C_LISTEN_MAX_CALLS_DEFAULT,                   // Backlog queue length for TCP/IP.
                                   reinterpret_cast<RPC_WSTR>((RPC_WSTR)L"tmp_endpoint"), // TCP/IP port to use
                                   NULL                                                   // No security
    );

    if (status)
        exit(status);

    // Registers the hello interface and auto listen
    // Equal to RpcServerRegisterIf + RpcServerListen
    status = RpcServerRegisterIf2(server_hello_v1_0_s_ifspec, // Interface to register.
                                  NULL,                       // Use the MIDL generated entry-point vector.
                                  NULL,                       // Use the MIDL generated entry-point vector.
                                  RPC_IF_ALLOW_LOCAL_ONLY | RPC_IF_AUTOLISTEN, // Forces use of security callback.
                                  RPC_C_LISTEN_MAX_CALLS_DEFAULT, // Use default number of concurrent calls.
                                  (unsigned)-1,                   // Infinite max size of incoming data blocks.
                                  SecurityCallback);              // Naive security callback.

    g_hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);               // 创建消息句柄
    hThread = CreateThread(NULL, 0, ThreadMakeMsg, NULL, 0, NULL); // 模拟消息生成
    while (1) {
        Sleep(10000); // 休眠，释放CPU
    }

    return 0;
}
